#include "defs.h"
#include "Exception.h"

Exception_T::Exception_T
(
	const unsigned int errorNumber, 
	const char * fileName, 
	const int lineNumber, 
	const char * funcSig,
	const char * format, 
	...
)
	: Code(errorNumber)
	, FileName(fileName)
	, LineNumber(lineNumber)
	, FuncSig(funcSig)
{
	FillMemory(Message, sizeof(Message), 0);
	GetErrorMessage(errorNumber, Message, sizeof(Message) / sizeof(Message[0]));

	char dataBuffer[0x400];
	FillMemory(dataBuffer, sizeof(dataBuffer), 0);
	if( format )
	{
		va_list args;
		va_start(args, format);
		_vsnprintf(dataBuffer, sizeof(dataBuffer) - 1, format, args);
		va_end(args);
	}

#ifdef _DEBUG
	Trace_T::WriteDebug(
		"Unexpected error 0x%08X occurred\r\n\r\n%s\r\n%S\r\n\r\nFilename: %s\r\nLine: %d\r\nFunction: %s\r\n",
		Code,
		dataBuffer,
		Message,
		FileName,
		LineNumber,
		FuncSig);
#endif
	
	Trace_T::WriteEvent(
		"Unexpected error 0x%08X occurred\r\n\r\n%s\r\n%S\r\n\r\nFilename: %s\r\nLine: %d\r\nFunction: %s\r\n",
		Code,
		dataBuffer,
		Message,
		FileName,
		LineNumber,
		FuncSig);
}

bool Exception_T::GetErrorMessageCLR
(
	unsigned int errorNumber, 
	wchar_t * msgBuffer, 
	unsigned int msgLength
)
{ 
	HINSTANCE msCorEE = LoadLibraryW(CLR_DLL);
	if( !msCorEE )
	{
		return false;
	}

	bool hadSuccess = false;

	LoadStringRC_T pLoadStringRC = (LoadStringRC_T)GetProcAddress(msCorEE, CLR_LOADSTRINGRC);
	if( pLoadStringRC )
	{
		HRESULT hr = pLoadStringRC(
			0x6000 + HRESULT_CODE(errorNumber), 
			msgBuffer, 
			msgLength, 
			true);

		hadSuccess = SUCCEEDED(hr);
	}

	FreeLibrary(msCorEE);
	return hadSuccess;
}

wchar_t * Exception_T::GetErrorMessage
(
	unsigned int  errorNumber, 
	wchar_t * msgBuffer, 
	unsigned int msgLength
)
{ 
	msgBuffer[0] = L'\0';

	if( (HRESULT_FACILITY(errorNumber) == FACILITY_URT) && (HRESULT_CODE(errorNumber) < 0x3000) )
	{ 
		if( GetErrorMessageCLR(errorNumber, msgBuffer, msgLength) )
		{ 
			return msgBuffer;
		}
	}

	else
	{ 
		if( FormatMessageW(
			FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
			0, 
			errorNumber, 
			0, 
			msgBuffer, 
			msgLength,
			0))
		{
			return msgBuffer;
		}
	}

	//
	// Getting here, means we were unable to find a proper error message
	//

	_snwprintf(
		msgBuffer, 
		msgLength,
		L"(unable to find a message for error 0x%08X)",
		errorNumber);

	return msgBuffer;
}